package fem2.gui.src;

import vtk.vtkCellArray;
import vtk.vtkDoubleArray;
import vtk.vtkPoints;
import vtk.vtkPolyData;
import fem2.Model;
import fem2.gui.pm.extr.Extractor2D;

public class HofemSolidElementsSource extends HofemSource {

	private Extractor2D extractor_;
	private int resolution_ = 20;
	private double maxU_;

	@Override
	protected void doExecute() {
		Model model = getModel().getModel();
		int d = model.getMesh().countFields();
		int nf = model.getMesh().countFaces();
		int offset = 0;

		vtkPolyData outPd = GetPolyDataOutput(); // hbui: this is important:
													// pointer to vtk data is
													// here
		vtkPoints points = new vtkPoints();
		vtkCellArray polys = new vtkCellArray();
		vtkCellArray lines = new vtkCellArray();
		vtkDoubleArray scalars = null;
		vtkDoubleArray vectors = null;
		outPd.SetPoints(points); // set the points to vtk data
		outPd.SetPolys(polys); // set the polygons
		outPd.SetLines(lines); // set the lines
		maxU_ = 0;

		if (getModel().solutionAvailable()) {
			scalars = new vtkDoubleArray();
			vectors = new vtkDoubleArray();
			vectors.SetNumberOfComponents(3);
			outPd.GetPointData().SetScalars(scalars);
			outPd.GetPointData().SetVectors(vectors);
		}

		int dim = model.getMesh().getDimension();
		for (int i = 0; i < model.getMesh().countNodes(); i++) {
			double[] p = model.getMesh().getNode(i).getPosition();
			if (dim == 2) {
				points.InsertNextPoint(p[0], p[1], 0);
			} else if (dim == 3) {
				points.InsertNextPoint(p);
			}
		}

		// for (int i = 0; i < model.countElements(); i++) {
		// Element e = model.getElement(i);
		// if (e instanceof Element2D) {
		// Element2D e2d = (Element2D) e;
		// Face f = e2d.getFace();
		// FunctionRnToR[] solutions = null;
		// FunctionR2ToRn q = f.getGeometry();
		// FunctionRnToR secondarySolution = null;
		// PolygonMesher qm = getMesher(f);
		//
		// Timer.getInstance().start("Face " + (i + 1) + "/" + nf);
		//
		// if (getModel().solutionAvailable()) {
		// solutions = new FunctionRnToR[d];
		// for (int j = 0; j < d; j++) {
		// solutions[j] = f.getSolution(j);
		// }
		// secondarySolution = extractor_.getFunction(e2d);
		// }
		//
		// for (Iterator<double[]> it = qm.pointIterator(); it.hasNext();) {
		// double[] xi = it.next();
		// double[] pt = q.valueAt(xi[0], xi[1]);
		//
		// // point
		// points.InsertNextPoint(pt[0], pt[1], 0);
		//
		// // results
		// if (getModel().solutionAvailable()) {
		// // assert primarySolution != null;
		// assert secondarySolution != null;
		// assert vectors != null;
		// assert scalars != null;
		// double[] u = new double[3];
		// Element e0 = model.getElement(0);
		// double s = secondarySolution.valueAt(xi[0], xi[1]);
		// double nu;
		// double[] uu = new double[d];
		//
		// for (int j = 0; j < d; j++) {
		// uu[j] = solutions[j].valueAt(xi[0], xi[1]);
		// }
		//
		// // collect displacement components
		// for (int k = 0; k < d; k++) {
		// if (e0.getFieldId(k) == FieldInfo.U1) {
		// u[0] = uu[k];
		// } else if (e0.getFieldId(k) == FieldInfo.U2) {
		// u[1] = uu[k];
		// } else if (e0.getFieldId(k) == FieldInfo.U3) {
		// u[2] = uu[k];
		// }
		// }
		// nu = LinAlg.norm2(3, u);
		//
		// // store
		// if (nu > maxU_) {
		// maxU_ = nu;
		// }
		// vectors.InsertNextTuple3(u[0], u[1], u[2]);
		// scalars.InsertNextValue(s);
		// }
		// }
		//
		// for (Iterator<int[]> it = qm.faceCellIterator(offset); it.hasNext();)
		// {
		// int[] cell = it.next();
		//
		// polys.InsertNextCell(4);
		// for (int j : cell) {
		// polys.InsertCellPoint(j);
		// }
		// }
		//
		// for (Iterator<int[]> it = qm.edgeCellIterator(offset); it.hasNext();)
		// {
		// int[] cell = it.next();
		//
		// lines.InsertNextCell(cell.length);
		// for (int j : cell) {
		// lines.InsertCellPoint(j);
		// }
		// }
		// offset += (resolution_ + 1) * (resolution_ + 1);
		//
		// Timer.getInstance().stop();
		// }
		// }
	}

	// public PolygonMesher getMesher(Face f) {
	// if (f.getBasis() instanceof XfemBasisOnR2) {
	// return new CrackedQuadMesher(resolution_);
	// }
	// if (f.getEdges().length == 4) {
	// return new QuadMesher(resolution_);
	// } else if (f.getEdges().length == 3) {
	// return new TriangleMesher(resolution_);
	// } else {
	// throw new Error();
	// }
	// }

	public double[] getVectorDataNormRange() {
		return new double[] { 0, maxU_ };
	}

	@Override
	protected void modelChanged() {
		Modified();
	}

	public void setExtractor(Extractor2D extractor) {
		extractor_ = extractor;
		Modified();
	}

	public void setResolution(int r) {
		resolution_ = r;
		Modified();
	}

	@Override
	protected void solutionDataChanged() {
		Modified();
	}
}
